//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using Eas.WebCrawler.Interfaces;

namespace Eas.WebCrawler.Model.Core {
    internal class BaseWebCrawlerEngine : Eas.WebCrawler.Common.BaseDisposable, Eas.WebCrawler.Interfaces.WebCrawlerEngine{

        WorkerContext _Context;
        Eas.WebCrawler.Interfaces.WorkerState _State = Eas.WebCrawler.Interfaces.WorkerState.Unstarted;

        /// <summary>Constructs a BaseWebCrawlerEngine from a <see cref="WorkerContext"/>.</summary>
        /// <param name="context"></param>
        public BaseWebCrawlerEngine(WorkerContext context) {
            _Context = context;
        }

        protected override void Dispose(bool isDisposing) {
            try {
                _Context.Dispose();
            }
            finally {
                base.Dispose(isDisposing);
            }
        }

        #region WebCrawlerEngine Members

        /// <summary>The store of requests to be processed.</summary>
        public RequestStore Store {
            get { return _Context.WebCrawlerContext.Store; }
        }

        /// <summary>Tell the engine to start crawling (or unpause if paused).</summary>
        public void Start() {
            if (_State == Eas.WebCrawler.Interfaces.WorkerState.Working)
                throw new InvalidOperationException("Can not call start while the engine is running.");
            
            _Context.StateTracker.RequestChange(Eas.WebCrawler.Interfaces.WorkerState.Working);

            if (_State != Eas.WebCrawler.Interfaces.WorkerState.Paused) {
                _Context.EventReporter.ReportTrace(TraceLevel.Critical, BaseProcessingState.EmptyState, "Engine Start was requested.");
                _Context.WebGateway.SetConnectionLimit(_Context.WebCrawlerContext.WorkerCount);
                _Context.EventReporter.ReportStarting();
                _Context.StateTracker.StartAllWorkers();
            }
            else {
                _Context.EventReporter.ReportTrace(TraceLevel.Critical, BaseProcessingState.EmptyState, "Engine UnPause was requested.");
                _Context.EventReporter.ReportUnpausing();
            }
            _State = Eas.WebCrawler.Interfaces.WorkerState.Working;
        }

        /// <summary>Tell the engine to stop crawling.</summary>
        public void Stop() {
            if (_State == Eas.WebCrawler.Interfaces.WorkerState.Stopped)
                throw new InvalidOperationException("Can not stop from stopped state");
            _Context.EventReporter.ReportTrace(TraceLevel.Critical, BaseProcessingState.EmptyState, "Engine Stop was requested.");
            _Context.StateTracker.RequestChange(Eas.WebCrawler.Interfaces.WorkerState.Stopped);
            _State = Eas.WebCrawler.Interfaces.WorkerState.Stopped;
        }

        /// <summary>Tell the engine to pause it's crawling.</summary>
        public void Pause() {
            if (_State != Eas.WebCrawler.Interfaces.WorkerState.Working)
                throw new InvalidOperationException("Can only call pause from working state");
            _Context.EventReporter.ReportTrace(TraceLevel.Critical, BaseProcessingState.EmptyState, "Engine Pause was requested.");
            _Context.StateTracker.RequestChange(Eas.WebCrawler.Interfaces.WorkerState.Paused);
            _State = Eas.WebCrawler.Interfaces.WorkerState.Paused;
        }

        /// <summary>The collection of events that this crawler will fire during processing.</summary>
        public Eas.WebCrawler.Interfaces.WebCrawlerEvents Events {
            get { return _Context.Events; }
        }

        #endregion
        //static Eas.WebCrawler.Common.Diagnostics.DeliTicketDispenser _ticketDispenser = new Eas.WebCrawler.Common.Diagnostics.DeliTicketDispenser();

    }
}
